<?php

class PostHandler extends CApplicationComponent
{
    public $requestHead=false,$requestBody=true;
    protected $url,$method,$host,$requestMethod,$port,$header,$body,$protocol='http';
    protected $error,$result;

    public function open($url='',$method='socket',$port=80)
    {
        $urlParts=explode('://',$url);
        if(!isset($urlParts[0]) || !isset($urlParts[1])){
            $this->error='Неправильный адрес запроса.';
        }

        if(!$this->error){
            $this->method=$method;
            $this->url=$url;
            $this->port=$port;

            if($method=='socket'){
                $this->protocol=$urlParts[0];
                $hostAndMethod=explode('/',$urlParts[1]);
                $this->host=array_shift($hostAndMethod);
                foreach($hostAndMethod as $name){
                    if(strlen($name)>1) $this->requestMethod.='/'.$name;
                }
                if($port==80 && (strpos($url,'https') || strpos($url,'ssl'))){
                    $this->protocol='ssl';
                    $this->port=443;
                }
            }
        }

        return $this;
    }

    public function setHeader($header)
    {
        $this->header=$header;
    }

    public function setBody($body)
    {
        $this->body=$body;
    }

    public function getError()
    {
        return $this->error;
    }

    public function getResult()
    {
        return $this->result;
    }

    public function sendRequest()
    {
        $methodName='send'.ucfirst($this->method).'Request';
        if(method_exists($this,$methodName)) return $this->$methodName();
        else $this->error='Не существует такого метода: "'.$this->method.'"';
        return false;
    }

    private function sendSocketRequest()
    {
        try{
            if(!$this->header){
                $this->header="POST ".$this->requestMethod." HTTP/1.1\r\nHost: ".$this->host."\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: ".
                    (strlen($this->body));
            }
            $socket=fsockopen('ssl://connect.mail.ru',443);
            fwrite($socket,$this->header."\r\n\r\n".$this->body."\r\n\r\n");
            $result='';
            while(!feof($socket)){
                $result.=fgets($socket,4098);
            };

            fclose($socket);

            return $this->readAnswer($result);
        }catch(Exception $e){
            $this->error='Не удалось получить данные от сервера: '.$e;
        }
        return false;
    }

    private function sendCurlRequest()
    {
        try{
            $curl=curl_init();
            if($this->protocol=='ssl' || $this->protocol=='https'){
                curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
                curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,0);
            }
            curl_setopt($curl,CURLOPT_URL,$this->url);
            curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
            curl_setopt($curl,CURLOPT_HEADER,$this->requestHead);
            curl_setopt($curl,CURLOPT_POST,1);
            curl_setopt($curl,CURLOPT_POSTFIELDS,$this->body);
            $out=curl_exec($curl);
            curl_close($curl);

            return $this->readAnswer($out);
        }catch(Exception $e){
            $this->error='Не удалось получить данные от сервера: '.$e;
        }
        return false;
    }

    private function readAnswer($answer)
    {
        //echo $answer; exit;
        if($this->result=json_decode($answer)) return true;
        if($this->result=json_decode(substr($answer,strpos($answer,'{')))) return true;
        $this->error='Не удалось прочитать ответ сервера';
        return false;
    }
}